package br.ucb.rest.negocio.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;

import br.ucb.rest.negocio.AbstractBusinessObject;
import br.ucb.rest.persistencia.dao.GenericDAO;
import br.ucb.rest.persistencia.vo.ContaPedidoVO;
import br.ucb.rest.persistencia.vo.ContaPedidoVOPK;
import br.ucb.rest.persistencia.vo.ContaVO;
import br.ucb.rest.persistencia.vo.GrupoPedidoVO;
import br.ucb.rest.persistencia.vo.PedidoVO;
import br.ucb.rest.persistencia.vo.TipoStatusVO;
import br.ucb.rest.util.Constantes;

public class GrupoPedidoBOS extends AbstractBusinessObject{
	private static GrupoPedidoBOS instance;
	private Logger logger = Logger.getLogger(GrupoPedidoBOS.class);
	
	private GrupoPedidoBOS() {
		super();
		logger.info("Singleton instanciado com sucesso!");
	}
	
	public static GrupoPedidoBOS getInstance() {
		if (instance == null) {
			instance = new GrupoPedidoBOS();
		}
		return instance;
	}

	
	
	public List<GrupoPedidoVO> recuperaAbertos(){
		EntityManager em = emf.createEntityManager();
		GenericDAO dao = GenericDAO.getInstance(em);
		try {
			List<GrupoPedidoVO> retorno = (List<GrupoPedidoVO>) dao.namedQueryListaResultados("GrupoPedidoVO.recuperarAbertos", null);
			return retorno;
		}catch (Exception e) {
			logger.error("",e);
			return null;
		}finally {
			GenericDAO.liberarInstancia();
			em.close();
		}
	}
	
	public List<GrupoPedidoVO> recuperaProntos(){
		EntityManager em = emf.createEntityManager();
		GenericDAO dao = GenericDAO.getInstance(em);
		try {
			List<GrupoPedidoVO> retorno = (List<GrupoPedidoVO>) dao.namedQueryListaResultados("GrupoPedidoVO.recuperarProntos", null);
			return retorno;
		}catch (Exception e) {
			logger.error("",e);
			return null;
		}finally {
			GenericDAO.liberarInstancia();
			em.close();
		}
	}
	
	public void fecharPedido(Integer chave) {
		EntityManager em = emf.createEntityManager();
		GenericDAO dao = GenericDAO.getInstance(em);
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			GrupoPedidoVO vo = (GrupoPedidoVO) dao.doFindByKey(GrupoPedidoVO.class, chave);
			vo.setTipoStatusVO(new TipoStatusVO(Constantes.STATUS_ENTREGUE));
			dao.doInsert(vo);
			transaction.commit();
		}catch (Exception e) {
			logger.error("Erro ao atualizar informacoes no banco de dados!",e);
			transaction.rollback();
		}finally {
			GenericDAO.liberarInstancia();
			em.close();
		}
		
	}

	public void pedidoPronto(Integer chave) {
		EntityManager em = emf.createEntityManager();
		GenericDAO dao = GenericDAO.getInstance(em);
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			GrupoPedidoVO vo = (GrupoPedidoVO) dao.doFindByKey(GrupoPedidoVO.class, chave);
			vo.setTipoStatusVO(new TipoStatusVO(Constantes.STATUS_NO_BALCAO));
			dao.doInsert(vo);
			transaction.commit();
		}catch (Exception e) {
			logger.error("Erro ao atualizar informacoes no banco de dados!",e);
			transaction.rollback();
		}finally {
			GenericDAO.liberarInstancia();
			em.close();
		}
		
	}
	
	public void incluirGrupo(GrupoPedidoVO grupo, String idIpad) {
		EntityManager em = emf.createEntityManager();
		GenericDAO dao = GenericDAO.getInstance(em);
		EntityTransaction transaction = em.getTransaction();
		try {
			transaction.begin();
			
			List<PedidoVO> pedidos = grupo.getColPedidoVO();
			grupo.setColPedidoVO(null);
			Number numeroPedido = (Number) em.createNativeQuery("select nextval ('restaurante.rst_grupo_pedido_numero_pedido_seq')").getSingleResult();
			grupo.setNumeroPedido(numeroPedido.intValue());
			dao.doInsert(grupo);
			
			for (PedidoVO pedido : pedidos) {
				pedido.setGrupoPedidoVO(grupo);
				dao.doInsert(pedido);
			}
			
			Map<String, Object> parametros = new HashMap<String, Object>(1);
			parametros.put("idIpad", idIpad);
			
			ContaVO conta;
			try {
				conta = (ContaVO) dao.namedQueryResultadoUnico("ContaVO.recuperarEmAberto", parametros);
				List<ContaPedidoVO> adicionar = new ArrayList<ContaPedidoVO>(pedidos.size());
				for (PedidoVO p : pedidos) {
					ContaPedidoVO item = new ContaPedidoVO();
					ContaPedidoVOPK chave = new ContaPedidoVOPK();
					chave.setNuConta(conta.getNuConta());
					chave.setNuPedido(p.getNuPedido());
					chave.setDtPedido(new Date(System.currentTimeMillis()));
					item.setContaPedidoVOPK(chave);
					adicionar.add(item);
				}
				dao.salvarVarios(adicionar);
			}catch (HibernateException e) {
				if (e.getCause().getClass() == NoResultException.class) {
					conta = new ContaVO();
					conta.setIdIpad(idIpad);
					conta.setDtAbertura(new Date(System.currentTimeMillis()));
					dao.doInsert(conta);
					
					List<ContaPedidoVO> colContaPedidoVO = new ArrayList<ContaPedidoVO>(pedidos.size());
					for (PedidoVO p : pedidos) {
						ContaPedidoVO item = new ContaPedidoVO();
						ContaPedidoVOPK chave = new ContaPedidoVOPK();
						chave.setNuConta(conta.getNuConta());
						chave.setNuPedido(p.getNuPedido());
						chave.setDtPedido(new Date(System.currentTimeMillis()));
						item.setContaPedidoVOPK(chave);
						colContaPedidoVO.add(item);
					}
					dao.salvarVarios(colContaPedidoVO);
				}
			}
			
			
			transaction.commit();
		}catch (Exception e) {
			logger.error("Erro ao incluir informa�›es no banco de dados!",e);
			transaction.rollback();
		}finally {
			GenericDAO.liberarInstancia();
			em.close();
		}
		
	}

}
